import math
import ffgeom as fg # Deprecated. Use geometry instead of ffgeom (code needs rework)
import geometry

class Molecules :
    """"""
    def __init__(self, points) :
        """
        initialize the list of points from the path
        """
        self.points = []
        for p in points :
            if p[0] != "Z" :
                self.points.append(geometry.Point(x=p[1][-2], y=p[1][-1]))
#        [self.points.append(geometry.Point(x=p[1][-2], y=p[1][-1]))
#        for p in points
#        if p[0] != "Z"
##        if self.points.count(geometry.Point(y=p[1][-1], x=p[1][-2])) == 0
#        ]
        #TODO correct the test of existence
    def rabbitEar(self) :
        """return a list of path data for the given CP"""
        a, b, c = self.points[0], self.points[1], self.points[2]
        # intersection of two bissectors give the center
        ab = geometry.lineFromTwoPoints(self.points[0], self.points[1])
        ca = geometry.lineFromTwoPoints(self.points[2], self.points[0])
        bc = geometry.lineFromTwoPoints(self.points[1], self.points[2])
        bis_a = geometry.lineBissector(b, a, c)
        bis_b = geometry.lineBissector(c, b, a)
        center = bis_a.intersection(bis_b)
        # tangeant of circles
        a_ = bc.orthogonalProjectionOfPoint(center)
        b_ = ca.orthogonalProjectionOfPoint(center)
        c_ = ab.orthogonalProjectionOfPoint(center)
        return [    [[a, center], 1],
                    [[b, center], 1],
                    [[c, center], 1],
                    [[center, a_], 0],
                    [[center, b_], 0],
                    [[center, c_], -1],
                ]

    def waterbomb(self,p=1) :
        """return a list with path data"""
        a = self.points[p-1]
        b = self.points[p]
        c = self.points[p+1]
        d = self.points[p+2]
        ab = geometry.vectorFromTwoPoints(a, b)
        bc = geometry.vectorFromTwoPoints(b, c)
        cd = geometry.vectorFromTwoPoints(c, d)
        da = geometry.vectorFromTwoPoints(d, a)
        l_ab = geometry.lineFromTwoPoints(a, b)
        l_bc = geometry.lineFromTwoPoints(b, c)
        l_cd = geometry.lineFromTwoPoints(c, d)
        l_da = geometry.lineFromTwoPoints(d, a)
        bis_a = geometry.lineBissector(b, a, d)
        bis_b = geometry.lineBissector(a, b, c)
        bis_c = geometry.lineBissector(b, c, d)
        bis_d = geometry.lineBissector(c, d, a)
        waterbomb_condition = ab.norm() + cd.norm() - (bc.norm() + da.norm() )
        if waterbomb_condition == 0 :
            o = bis_a.intersection(bis_b)
            return [    [[a, o ], 1],
                        [[b, o ], 1],
                        [[c, o ], 1],
                        [[d, o ], 1],
                        [[o, l_ab.orthogonalProjectionOfPoint(o)], -1],
                        [[o, l_bc.orthogonalProjectionOfPoint(o)], 0],
                        [[o, l_cd.orthogonalProjectionOfPoint(o)], 0],
                        [[o, l_da.orthogonalProjectionOfPoint(o)], 0]
                    ]
        elif waterbomb_condition < 0 :
            o1 = bis_a.intersection(bis_b)
            o2 = bis_c.intersection(bis_d)
            return [    [[a, o1 ], 1],
                        [[b, o1 ], 1],
                        [[c, o2 ], 1],
                        [[d, o2 ], 1],
                        [[o1, o2], 1],
                        [[o1, l_ab.orthogonalProjectionOfPoint(o1)], -1],
                        [[o1, l_da.orthogonalProjectionOfPoint(o1)], 0],
                        [[o1, l_bc.orthogonalProjectionOfPoint(o1)], 0],
                        [[o2, l_cd.orthogonalProjectionOfPoint(o2)], 0],
                        [[o2, l_da.orthogonalProjectionOfPoint(o2)], 0],
                        [[o2, l_bc.orthogonalProjectionOfPoint(o2)], 0]
                    ]
        elif waterbomb_condition > 0 :
            o1 = bis_d.intersection(bis_a)
            o2 = bis_c.intersection(bis_b)
            return [    [[a, o1 ], -1],
                        [[d, o1 ], -1],
                        [[c, o2 ], -1],
                        [[b, o2 ], -1],
                        [[o1, o2], -1],
                        [[o1, l_da.orthogonalProjectionOfPoint(o1)], 1],
                        [[o1, l_ab.orthogonalProjectionOfPoint(o1)], 0],
                        [[o1, l_cd.orthogonalProjectionOfPoint(o1)], 0],
                        [[o2, l_bc.orthogonalProjectionOfPoint(o2)], 1],
                        [[o2, l_ab.orthogonalProjectionOfPoint(o2)], 0],
                        [[o2, l_cd.orthogonalProjectionOfPoint(o2)], 0],
                    ]

    # Cleanup Ok before this point
    def arrowhead(self,p=0,l=.8) :
        """return a list with path data"""
        a = self.points[p]
        b = self.points[p+1]
        c = self.points[p+2]
        d = self.points[p+3]
        ab = geometry.vectorFromTwoPoints(a, b)
        bc = geometry.vectorFromTwoPoints(b, c)
        cd = geometry.vectorFromTwoPoints(c, d)
        da = geometry.vectorFromTwoPoints(d, a)
        l_ab = geometry.lineFromTwoPoints(a, b)
        l_bc = geometry.lineFromTwoPoints(b, c)
        l_cd = geometry.lineFromTwoPoints(c, d)
        l_da = geometry.lineFromTwoPoints(d, a)
        bis_a = geometry.lineBissector(b, a, d)
        bis_b = geometry.lineBissector(c, b, a)
        bis_c = geometry.lineBissector(b, c, d)
        bis_d = geometry.lineBissector(c, d, a) 
        o1 = bis_a.intersection(bis_b)
        o2 = bis_c.intersection(bis_d)
        z1 = a.pointAtRatio(o1, l)
        sym_z1 = a.pointAxialSymmetry(geometry.lineFromTwoPoints(d,z1))
        sym_da = geometry.lineFromTwoPoints(sym_z1,d)
        z2 = sym_da.intersection(bis_c)
        z3 = bis_c.intersection(geometry.lineBissector(c , d, z2))
        z4 = geometry.lineFromTwoPoints(d, z2).orthogonalProjectionOfPoint(z1)
        z5 = geometry.lineFromTwoPoints(b, z2).orthogonalProjectionOfPoint(z1) 
        z6 = geometry.lineFromTwoPoints(z1,z4).intersection(geometry.lineFromTwoPoints(d, z3))
        z7 = geometry.lineFromTwoPoints(z1,z5).intersection(geometry.lineFromTwoPoints(b, z3) )
        
        return [    [[a, z1], -1],
                    [[b, z1], -1],
                    [[d, z1], -1],
                    [[z1, l_da.orthogonalProjectionOfPoint(z1)], 0],
                    [[z1, l_ab.orthogonalProjectionOfPoint(z1)], 1],
                    [[d, z2], 1],
                    [[b, z2], 1],
                    [[d, z3], -1],
                    [[b, z3], -1],
                    [[z2, z3], 1],
                    [[z3, c], -1],
                    [[z1, z2], -1],
                    [[z1, z4], 1],
                    [[z1, z5], 0],
                    [[z4, z6], -1],
                    [[z5, z7], 0],
                    [[z6, l_cd.orthogonalProjectionOfPoint(z6)], 1],
                    [[z7, l_bc.orthogonalProjectionOfPoint(z7)], 0],
                ]

    def gusset(self) :
        """return a list with path data"""
        pass    
        
if __name__ == '__main__' :
    from pprint import *
    import simplepath
    path = "M 0 0 L 1 12 L 10 10 L 15 0 Z"
    pathData = simplepath.parsePath(path)
    p = Molecules(pathData)
    print p.waterbomb()
    #print p.arrowhead(0,.5)